package vashion.azeroth.core.service.tran.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import vashion.azeroth.common.tran.GeneralOrderUtil;
import vashion.azeroth.contant.AzerothConstants;
import vashion.azeroth.contant.GenericErrorEnum;
import vashion.azeroth.contant.TranErrorEnum;
import vashion.azeroth.core.common.RechargeTransform;
import vashion.azeroth.core.manager.item.BaseItemSkuManager;
import vashion.azeroth.core.manager.personal.tran.PersonalDisburseManager;
import vashion.azeroth.core.manager.personal.tran.PersonalFreezeTranDetailManager;
import vashion.azeroth.core.manager.personal.tran.PersonalRechargeOrderManager;
import vashion.azeroth.core.manager.personal.tran.PersonalSnapshotManager;
import vashion.azeroth.core.manager.personal.tran.PersonalTranDetailManager;
import vashion.azeroth.core.manager.personal.tran.PersonalVAccountManager;
import vashion.azeroth.core.personal.pojo.PersonalMember;
import vashion.azeroth.core.personal.pojo.PersonalMemberVip;
import vashion.azeroth.core.personal.tran.pojo.PersonalDisburse;
import vashion.azeroth.core.personal.tran.pojo.PersonalFreezeTranDetail;
import vashion.azeroth.core.personal.tran.pojo.PersonalRechargeOrder;
import vashion.azeroth.core.personal.tran.pojo.PersonalSnapshot;
import vashion.azeroth.core.personal.tran.pojo.PersonalTranDetail;
import vashion.azeroth.core.personal.tran.pojo.PersonalVAccount;
import vashion.azeroth.core.result.ApiResult;
import vashion.azeroth.core.service.PersonalMemberVipService;
import vashion.azeroth.core.service.base.BaseService;
import vashion.azeroth.core.service.tran.PersonalRechargeService;
import vashion.azeroth.core.service.tran.PersonalSnapshotService;

import com.alibaba.fastjson.JSON;
import com.pingplusplus.Pingpp;
import com.pingplusplus.exception.APIConnectionException;
import com.pingplusplus.exception.APIException;
import com.pingplusplus.exception.AuthenticationException;
import com.pingplusplus.exception.InvalidRequestException;
import com.pingplusplus.model.Charge;

@Service
public class PersonalRechargeServiceImpl extends BaseService implements PersonalRechargeService<Charge> {
	
	private final static Logger log = LoggerFactory.getLogger(PersonalRechargeServiceImpl.class);

	@Autowired
	private PersonalRechargeOrderManager rechargeOrderManager;
	@Autowired
	private PersonalDisburseManager disburseManager;
	@Autowired
	private PersonalVAccountManager vaccountManager;
	@Autowired
	private PersonalTranDetailManager tranDetailManager;
	@Autowired
	private PersonalFreezeTranDetailManager FreezeTranDetailManager;
	@Autowired
	private PersonalSnapshotManager snapshotManager;
	@Autowired
	private PersonalSnapshotService snapshotService;
	@Autowired
	private PersonalMemberVipService<PersonalMemberVip> memberVipService;
	@Autowired
	private BaseItemSkuManager baseItemSkuManager;
	
	@Override
	public ApiResult<String> obtainChargeCredential(PersonalRechargeOrder order, PersonalMember member, String clientIp) {
		try {
			PersonalRechargeOrder recharge = buildRechargeOrder(order, member.getMemberName());
			recharge = rechargeOrderManager.save(recharge);
		
			if(null != recharge) {
				Pingpp.apiKey = "sk_live_i5eb1OjHSSWD10C0eLTSGuP0";
				Charge result = Charge.create(buildPingXXParams(recharge, clientIp));
				
				String charge = JSON.toJSONString(result);
				
				return ApiResult.newSuccessResult(charge);
			} else {
				log.error("充值订单创建失败");
				return ApiResult.newErrorResult(GenericErrorEnum.INSERT_ERROR.getErrorCode(), "充值订单" + GenericErrorEnum.INSERT_ERROR.getErrorMessage());
			}
			
		} catch (AuthenticationException e) {
			log.error("", e);
			return ApiResult.newErrorResult(TranErrorEnum.CALL_PING_ERROR.getErrorCode(), TranErrorEnum.CALL_PING_ERROR.getErrorMessage());
		} catch (InvalidRequestException e) {
			log.error("", e);
			return ApiResult.newErrorResult(TranErrorEnum.CALL_PING_ERROR.getErrorCode(), TranErrorEnum.CALL_PING_ERROR.getErrorMessage());
		} catch (APIConnectionException e) {
			log.error("", e);
			return ApiResult.newErrorResult(TranErrorEnum.CALL_PING_ERROR.getErrorCode(), TranErrorEnum.CALL_PING_ERROR.getErrorMessage());
		} catch (APIException e) {
			log.error("", e);
			return ApiResult.newErrorResult(TranErrorEnum.CALL_PING_ERROR.getErrorCode(), TranErrorEnum.CALL_PING_ERROR.getErrorMessage());
		} catch (Exception e) {
			log.error("系统异常", e);
			return ApiResult.newErrorResult(GenericErrorEnum.SYSTEM_ERROR.getErrorCode(), GenericErrorEnum.SYSTEM_ERROR.getErrorMessage());
		}
	}
	
	public ApiResult<String> obtainDisburseCredential(String disburseNo, String modeName, PersonalMember member, String clientIp) {
		try {
			PersonalDisburse disburse = disburseManager.getByDisburseNo(disburseNo);
			
			ApiResult<String> apiResult = checkDisburse(disburse);
			if(null != apiResult) {
				return apiResult;
			}
			
			PersonalRechargeOrder rechargeOrder = rechargeOrderManager.getRechargeOrderByDisburseNo(disburseNo);
			
			/**
			 * 无充值订单先创建充值订单
			 * 更换充值方式重新生成充值订单
			 */
			if(null == rechargeOrder || !rechargeOrder.getModeName().equals(modeName)) {
				PersonalRechargeOrder rechargeOrderParam = new PersonalRechargeOrder();
				rechargeOrderParam.setMemberId(disburse.getBuyerMemberId());
				rechargeOrderParam.setModeName(modeName);
				rechargeOrderParam.setAmount(disburse.getOrderTotalPrice());
				rechargeOrderParam.setDisburseNo(disburseNo);
				rechargeOrder = buildRechargeOrder(rechargeOrderParam, member.getMemberName());
				rechargeOrder = rechargeOrderManager.save(rechargeOrder);
			}
			
			if(null != rechargeOrder) {
				Pingpp.apiKey = "sk_live_i5eb1OjHSSWD10C0eLTSGuP0";
				Charge result = Charge.create(buildPingXXParams(rechargeOrder, clientIp));
				
				String charge = JSON.toJSONString(result);
				
				return ApiResult.newSuccessResult(charge);
			} else {
				log.error("充值订单创建失败");
				return ApiResult.newErrorResult(GenericErrorEnum.INSERT_ERROR.getErrorCode(), "充值订单" + GenericErrorEnum.INSERT_ERROR.getErrorMessage());
			}
			
		} catch (AuthenticationException e) {
			log.error("", e);
			return ApiResult.newErrorResult(TranErrorEnum.CALL_PING_ERROR.getErrorCode(), TranErrorEnum.CALL_PING_ERROR.getErrorMessage());
		} catch (InvalidRequestException e) {
			log.error("", e);
			return ApiResult.newErrorResult(TranErrorEnum.CALL_PING_ERROR.getErrorCode(), TranErrorEnum.CALL_PING_ERROR.getErrorMessage());
		} catch (APIConnectionException e) {
			log.error("", e);
			return ApiResult.newErrorResult(TranErrorEnum.CALL_PING_ERROR.getErrorCode(), TranErrorEnum.CALL_PING_ERROR.getErrorMessage());
		} catch (APIException e) {
			log.error("", e);
			return ApiResult.newErrorResult(TranErrorEnum.CALL_PING_ERROR.getErrorCode(), TranErrorEnum.CALL_PING_ERROR.getErrorMessage());
		} catch (Exception e) {
			log.error("系统异常", e);
			return ApiResult.newErrorResult(GenericErrorEnum.SYSTEM_ERROR.getErrorCode(), GenericErrorEnum.SYSTEM_ERROR.getErrorMessage());
		}
		
	}
	
	private ApiResult<String> checkDisburse(PersonalDisburse disburse) {
		if(null == disburse) {
			return ApiResult.newErrorResult(GenericErrorEnum.ORDER_NOT_EXIST.getErrorCode(), "消费" + GenericErrorEnum.ORDER_NOT_EXIST.getErrorMessage());
		}
		
		//消费订单状态不正确不能付款
		if(!(disburse.getStatus() == AzerothConstants.PersonalDisburse.DisburseStatus.created 
				|| disburse.getStatus() == AzerothConstants.PersonalDisburse.DisburseStatus.supplier_accept)) {
			return ApiResult.newErrorResult(GenericErrorEnum.STATUS_ERROR.getErrorCode(), "消费订单" + GenericErrorEnum.STATUS_ERROR.getErrorMessage());
		}
		
		//校验商品库存
//		for (PersonalSnapshot snapshot : disburse.getSnapshots()) {
//			Boolean canSale = baseItemSkuManager.canSale(snapshot.getSkuId(), snapshot.getQuantity());
//			if(!canSale) {
//				log.error("商品库存不足,商品ID:" + snapshot.getSkuId() + ", 商品title：" + snapshot.getTitle());
//				return ApiResult.newErrorResult(TranErrorEnum.ITEM_COUNT_NOT_ENOUGH.getErrorCode(), "商品" + snapshot.getTitle() + TranErrorEnum.ITEM_COUNT_NOT_ENOUGH.getErrorMessage());
//			}
//		}
		
		return null;
	}
	
	/**
	 * 标识订单中商品价格是否有变化
	 * 
	 * @param hisSnapshots
	 * @param snapshotMap
	 * @param isVip
	 * @return
	 */
	public Boolean isChange(List<PersonalSnapshot> hisSnapshots, Map<Long, PersonalSnapshot> snapshotMap, Boolean isVip) {
		for (PersonalSnapshot snapshot : hisSnapshots) {
			PersonalSnapshot freshSnapshot = snapshotMap.get(snapshot.getSkuId());
			if(isVip) {
				if(snapshot.getPrice() != freshSnapshot.getVipPrice()) {
					return Boolean.TRUE;
				}
			} else {
				if(snapshot.getPrice() != freshSnapshot.getPrice()) {
					return Boolean.TRUE;
				}
			}
		}
		return Boolean.FALSE;
	}
	
	/**
	 * 重新计算订单总额
	 * 
	 * @param hisSnapshots
	 * @param snapshotMap
	 * @param isVip
	 * @return
	 */
	public long recalTotalPrice(List<PersonalSnapshot> hisSnapshots, Map<Long, PersonalSnapshot> snapshotMap, Boolean isVip) {
		long totalPrice = 0;
		for (PersonalSnapshot snapshot : hisSnapshots) {
			if(isVip) {
				snapshot.setPrice(snapshotMap.get(snapshot.getSkuId()).getVipPrice());
			} else {
				snapshot.setPrice(snapshotMap.get(snapshot.getSkuId()).getPrice());
			}
			totalPrice += snapshot.getPrice()*snapshot.getQuantity();
		}
		
		return totalPrice;
	}
	
	/**
	 * 持有商品快照价格
	 * 
	 * @param snapshots
	 * @return
	 */
	public List<PersonalSnapshot> holdHisSnapshot(List<PersonalSnapshot> snapshots) {
		List<PersonalSnapshot> hisSnapshots = new ArrayList<PersonalSnapshot>();
		for (PersonalSnapshot snapshot : snapshots) {
			PersonalSnapshot personalSnapshot = new PersonalSnapshot();
			personalSnapshot.setDisburseNo(snapshot.getDisburseNo());
			personalSnapshot.setSkuId(snapshot.getSkuId());
			personalSnapshot.setPrice(snapshot.getPrice());
			personalSnapshot.setQuantity(snapshot.getQuantity());
			hisSnapshots.add(personalSnapshot);
		}
		
		return hisSnapshots;
	}
	
	/**
	 * 构建Ping++需要的参数
	 * @param recharge
	 * @param clientIp
	 * @return
	 */
	private Map<String, Object> buildPingXXParams(PersonalRechargeOrder recharge, String clientIp) {
		Map<String, Object> chargeParams = new HashMap<String, Object>();
		chargeParams.put("order_no",  recharge.getRechargeOrderNo());
		chargeParams.put("amount", recharge.getAmount());
//		chargeParams.put("amount", 1);
		chargeParams.put("channel",  recharge.getModeName());
		chargeParams.put("currency", "cny");
		chargeParams.put("client_ip",  clientIp);
		chargeParams.put("subject",  "消费");
		chargeParams.put("body",  "消费");
		  
		Map<String, String> app = new HashMap<String, String>();
		app.put("id", "app_O0iv9CPGufLSXzjP");
		chargeParams.put("app", app);
		
		return chargeParams;
	}
	
	private PersonalRechargeOrder buildRechargeOrder(PersonalRechargeOrder order, String memberName) {
		order.setRechargeOrderNo(GeneralOrderUtil.generalRechargeOrderNo(RechargeTransform.getOrderNoPre(order.getModeName()), 6));
		order.setMemberName(memberName);
		order.setStatus(AzerothConstants.PersonalRechargeOrder.RechargeOrderStatus.created);
		order.setTimeAdd(new Date());
		return order;
	}

	@Transactional
	@Override
	public ApiResult<String> vpay(String disburseNo, String clientIp) {
		PersonalDisburse disburse = disburseManager.getByDisburseNo(disburseNo);
//		if(null == disburse) {
//			return ApiResult.newErrorResult(GenericErrorEnum.ORDER_NOT_EXIST.getErrorCode(), "消费" + GenericErrorEnum.ORDER_NOT_EXIST.getErrorMessage());
//		}
//		
//		//消费订单状态不正确不能付款
//		if(disburse.getStatus() != 0) {
//			return ApiResult.newErrorResult(GenericErrorEnum.STATUS_ERROR.getErrorCode(), "消费订单" + GenericErrorEnum.STATUS_ERROR.getErrorMessage());
//		}
//		
//		//校验商品库存
//		for (PersonalSnapshot snapshot : disburse.getSnapshots()) {
//			Boolean canSale = baseItemSkuManager.canSale(snapshot.getSkuId(), snapshot.getQuantity());
//			if(!canSale) {
//				log.error("商品库存不足,商品ID:" + snapshot.getSkuId() + ", 商品title：" + snapshot.getTitle());
//				return ApiResult.newErrorResult(TranErrorEnum.ITEM_COUNT_NOT_ENOUGH.getErrorCode(), "商品" + snapshot.getTitle() + TranErrorEnum.ITEM_COUNT_NOT_ENOUGH.getErrorMessage());
//			}
//		}
		
		ApiResult<String> apiResult = checkDisburse(disburse);
		if(null != apiResult) {
			return apiResult;
		}
		
		List<PersonalSnapshot> hisSnapshots = holdHisSnapshot(disburse.getSnapshots());
		
		//用最新商品价格填充消费订单
		List<PersonalSnapshot> snapshots = snapshotService.fillingSnapshot(disburse.getSnapshots());
		
		//构建Map减少循环
		Map<Long, PersonalSnapshot> snapshotMap = new HashMap<Long, PersonalSnapshot>();
		for (PersonalSnapshot snapshot : snapshots) {
			snapshotMap.put(snapshot.getSkuId(), snapshot);
		}
		
		Boolean isVip = memberVipService.isVip(disburse.getBuyerMemberId());
		
		boolean isChanged = isChange(hisSnapshots, snapshotMap, isVip);
		
		//订单中商品价格已变化需更新订单金额
		if(isChanged) {
			long totalPrice = recalTotalPrice(hisSnapshots, snapshotMap, isVip);
			
			disburse.setDisburseNo(disburse.getDisburseNo());
			disburse.setTotalPrice(totalPrice);
			disburse.setTimeEdit(new Date());
			disburseManager.update(disburse);
			
			for (PersonalSnapshot snapshot : hisSnapshots) {
				snapshotManager.update(snapshot);
			}
		}
		
		PersonalVAccount vaccount = vaccountManager.get(disburse.getBuyerMemberId());
		
		if(null == vaccount || (disburse.getTotalPrice() > vaccount.getUseableBalance())) {
			return ApiResult.newErrorResult(TranErrorEnum.V_NOT_ENOUGH_ERROR.getErrorCode(), TranErrorEnum.V_NOT_ENOUGH_ERROR.getErrorMessage());
		}
		
		tranDetailManager.update(buildTranDetail(vaccount, disburse));
		vaccountManager.update(buildVaccount(vaccount, disburse));
		disburseManager.update(buildDisburse(disburse));
		
		return ApiResult.newSuccessResult();
	}
	
	private PersonalTranDetail buildTranDetail(PersonalVAccount vaccount, PersonalDisburse disburse) {
		PersonalTranDetail tranDetail = new PersonalTranDetail();
		tranDetail.setTranNo(disburse.getDisburseNo());
		tranDetail.setIncome(0);
		tranDetail.setPayout(disburse.getTotalPrice());
		tranDetail.setMemberId(disburse.getBuyerMemberId());
		tranDetail.setMemberName(disburse.getBuyerMemberName());
		tranDetail.setPreBalance(vaccount.getTotalBalance());
		tranDetail.setCurBalance(vaccount.getTotalBalance()-disburse.getTotalPrice());
		tranDetail.setTranType(AzerothConstants.PersonalTranDetail.TranDetailStatus.disburse);
		tranDetail.setTimeAdd(new Date());
		tranDetail.setUserAdd(disburse.getBuyerMemberName());
		tranDetail.setRemark("V币支付");
		
		return tranDetail;
	}
	
	private PersonalVAccount buildVaccount(PersonalVAccount vaccount, PersonalDisburse disburse) {
		PersonalVAccount account = new PersonalVAccount();
		account.setvAccountId(vaccount.getvAccountId());
		account.setUseableBalance(vaccount.getUseableBalance()-disburse.getTotalPrice());
		account.setTotalBalance(vaccount.getTotalBalance()-disburse.getTotalPrice());
		account.setTimeEdit(new Date());
		
		return account;
	}
	
	private PersonalDisburse buildDisburse(PersonalDisburse disburse) {
		PersonalDisburse paramDisburse = new PersonalDisburse();
		paramDisburse.setDisburseNo(disburse.getDisburseNo());
		paramDisburse.setStatus(AzerothConstants.PersonalDisburse.DisburseStatus.agent_payment);
		paramDisburse.setTimeEdit(new Date());
		
		return paramDisburse;
	}

	@Override
	public ApiResult<List<PersonalRechargeOrder>> getRechargeOrderList(PersonalRechargeOrder rechargeOrder) {
		
		ApiResult<List<PersonalRechargeOrder>> result = new ApiResult<List<PersonalRechargeOrder>>();
		
		int totalCount = rechargeOrderManager.findCnt(rechargeOrder);
		initPages(rechargeOrder, totalCount);
		List<PersonalRechargeOrder> orderList = rechargeOrderManager.find(rechargeOrder);
		
		result.setData(orderList);
		result.setTotalCount(totalCount);
		
		return result;
	}

	/**
	 * 确认订单,可用金额增加,冻结金额减少,总金额不变
	 */
	@Transactional
	@Override
	public ApiResult<String> confirmRechargeOrder(String rechargeOrderNo) {
		
		PersonalRechargeOrder rechargeOrder = rechargeOrderManager.getRechargeOrderByRechargeOrderNoWithLock(rechargeOrderNo);
		
		if(null != rechargeOrder && rechargeOrder.getStatus() == AzerothConstants.PersonalRechargeOrder.RechargeOrderStatus.waitConfirmed) {
			PersonalVAccount vaccount = vaccountManager.getByMemberId(rechargeOrder.getMemberId());
			
			tranDetailManager.save(buildConfirmTranDetail(vaccount, rechargeOrder));
			FreezeTranDetailManager.save(buildConfirmFreezenDetail(vaccount, rechargeOrder));
			vaccountManager.update(buildConfirmVAccount(vaccount, rechargeOrder));
			
			rechargeOrder.setStatus(AzerothConstants.PersonalRechargeOrder.RechargeOrderStatus.success);
			rechargeOrderManager.update(rechargeOrder);
		} else {
			return ApiResult.newErrorResult(GenericErrorEnum.STATUS_ERROR.getErrorCode(), "订单" + GenericErrorEnum.STATUS_ERROR.getErrorMessage());
		}
		
		return ApiResult.newSuccessResult();
	}
	
	private PersonalTranDetail buildConfirmTranDetail(PersonalVAccount vaccount, PersonalRechargeOrder rechargeOrder) {
		PersonalTranDetail tranDetail = new PersonalTranDetail();
		tranDetail.setTranNo(rechargeOrder.getRechargeOrderNo());
		tranDetail.setIncome(rechargeOrder.getAmount());
		tranDetail.setPayout(0);
		tranDetail.setMemberId(rechargeOrder.getMemberId());
		tranDetail.setMemberName(rechargeOrder.getMemberName());
		tranDetail.setPreBalance(vaccount.getUseableBalance());
		tranDetail.setCurBalance(vaccount.getUseableBalance() + rechargeOrder.getAmount());
		tranDetail.setTranType(AzerothConstants.PersonalTranDetail.TranDetailStatus.recharge);
		tranDetail.setTimeAdd(new Date());
		tranDetail.setUserAdd(rechargeOrder.getMemberName());
		tranDetail.setRemark("后台确认充值");
		
		return tranDetail;
	}
	
	private PersonalFreezeTranDetail buildConfirmFreezenDetail(PersonalVAccount vaccount, PersonalRechargeOrder rechargeOrder) {
		PersonalFreezeTranDetail freezeTranDetail = new PersonalFreezeTranDetail();
		freezeTranDetail.setTranNo(rechargeOrder.getRechargeOrderNo());
		freezeTranDetail.setIncome(0);
		freezeTranDetail.setPayout(rechargeOrder.getAmount());
		freezeTranDetail.setMemberId(rechargeOrder.getMemberId());
		freezeTranDetail.setMemberName(rechargeOrder.getMemberName());
		freezeTranDetail.setPreBalance(vaccount.getFreezeBalance());
		freezeTranDetail.setCurBalance(vaccount.getFreezeBalance() - rechargeOrder.getAmount());
		freezeTranDetail.setTranType(AzerothConstants.PersonalTranDetail.TranDetailStatus.disburse);
		freezeTranDetail.setTimeAdd(new Date());
		freezeTranDetail.setUserAdd(rechargeOrder.getMemberName());
		freezeTranDetail.setRemark("后台确认解冻");
		
		return freezeTranDetail;
	}
	
	private PersonalVAccount buildConfirmVAccount(PersonalVAccount vaccount, PersonalRechargeOrder rechargeOrder) {
		vaccount.setUseableBalance(vaccount.getUseableBalance() + rechargeOrder.getAmount());
		vaccount.setFreezeBalance(vaccount.getFreezeBalance() - rechargeOrder.getAmount());
		
		return vaccount;
	}
	

}
